import express from "express";
import { PrismaClient, mp_router as PRouter } from "@prisma/client";
import { CreateId, Check, Result, Time, Utils, redis, Token } from "@/utils";

const prisma = new PrismaClient();
const router = express.Router();

/** 管理员账户登录/注册 */
router.post("/admin", async (req, res) => {
   const { account, phone, pwd, code, smgId }: Login.Admin = req.body;

   if (!Check.Required([phone, pwd])) return res.send(Result.Error("参数错误"));

   // 检测是否已存在账号
   // const hasUser = await userController.checkUser();
   // if (hasUser) return Result.Error("当前系统已存在管理员账号");

   const checkRes = await prisma.sms.findFirst({
      where: {
         phone: phone,
         code: code,
         id: smgId,
         send_time: {
            gte: new Date(Time.Now().getTime() - 600000)
         }
      }
   });

   if (!checkRes) return Result.Error("验证码错误");

   const salt = Utils.GenerateSalt();

   const password = Utils.GeneratePWD(pwd, salt);

   let role = await prisma.mp_role.findFirst({ where: { super_admin: true } }); // 检查是否存在超级管理员
   // 获取所有路由配置
   const routerList = await prisma.mp_router.findMany();

   const routerTree = Utils.ListToTree(routerList);
   // 如果超级管理员不存在
   if (!role) {
      const role_id = await CreateId.One("mp_role");
      // 创建超级管理员角色
      role = await prisma.mp_role.create({
         data: {
            id: role_id,
            name: "超级管理员",
            super_admin: true,
            created_by: "adminSignIn",
            status: "OPEN",
            permission: "",
            created_time: Time.Now()
         }
      });
   }

   /** 创建用户 */
   const userId = await CreateId.One("user");
   const user = await prisma.user.create({
      data: {
         id: userId,
         account: account,
         phone: phone,
         role_id: role.id,
         password,
         status: "NORMAL",
         salt,
         created_time: Time.Now(),
         last_login_time: Time.Now()
      }
   });

   const token = Token.Encrypt(user.id); // 生成 token
   await redis.set(user.id, JSON.stringify({ token })); // 将数据存入 redis 中

   res.send(
      Result.OK({
         token,
         userInfo: {
            name: user.name,
            account: user.account,
            phone: user.phone,
            role_id: user.role_id,
            avatar: user.avatar
         },
         router: routerTree
      })
   );
});

/** 密码登录 */
router.post("/password", async (req, res) => {
   const { account, pwd }: Login.Password = req.body;
   if (!Check.Required([account, pwd])) return res.send(Result.Error("参数错误"));

   // 查询当前账户是否存在
   const user = await prisma.user.findFirst({
      where: { OR: [{ account }, { phone: account }] }
   });

   if (!user) return res.send(Result.Error("当前用户不存在"));

   /** 通过加密盐生成加密密码 */
   const password = Utils.GeneratePWD(pwd, user.salt);

   if (password != user.password) return res.send(Result.Error("密码错误"));

   console.log("user", user);

   const token = Token.Encrypt(user.id);

   // 将用户状态存入 redis 中
   let userLocalStr = await redis.get(user.id); // 检测 redis 中是否存在记录

   let userLocal = { token };
   if (!!userLocalStr && Check.StringIsJSON(userLocalStr)) {
      userLocal = JSON.parse(userLocalStr as string);

      userLocal.token = token;
   }

   userLocalStr = JSON.stringify(userLocal);

   /** 写入数据至 redis */
   await redis.set(user.id, userLocalStr);

   /** 更新最后登录时间 */
   await prisma.user.update({ where: { id: user.id }, data: { last_login_time: Time.Now() } });

   // start --- 获取用户权限列表

   // 读取路由列表
   const router = await prisma.mp_router.findMany();
   let routerTree;
   // 读取用户当前角色信息
   const role = await prisma.mp_role.findUnique({ where: { id: user.role_id } });
   if (!role) return res.send(Result.Error("当前用户未分配角色"));

   // 如果当前角色为超级管理员，返回所有页面
   if (role.super_admin) {
      routerTree = Utils.ListToTree(router);
   } else {
      const permission = role.permission.split(","); // 将权限字段还原为 id 数组
      const routerMap = new Map<string, PRouter>(); // 创建路由 map 对象，key 为路由 id ，value 为路由信息
      router.forEach(item => routerMap.set(item.id, item)); // 将路由数组转换为 map 对象

      const roleRouter = permission.map(item => routerMap.get(item)); // 遍历权限列表，将符合条件的路由信息组合为新数组

      routerTree = Utils.ListToTree(roleRouter); // 将扁平结构转化为树状结构
   }

   // end --- 获取用户权限列表

   res.send(
      Result.OK({
         token,
         userInfo: {
            name: user.name,
            account: user.account,
            phone: user.phone,
            role_id: user.role_id,
            avatar: user.avatar
         },
         router: routerTree
      })
   );
});

/** 短信登录 */
router.post("/message", async (req, res) => {
   const { account, code, smgId }: Login.Message = req.body;
   if (!Check.Required([account, code, smgId])) return res.send(Result.Error("参数错误"));

   const checkRes = await prisma.sms.findFirst({
      where: {
         phone: account,
         code,
         id: smgId,
         send_time: {
            gte: new Date(Time.Now().getTime() - 600000)
         }
      }
   });

   if (!checkRes) return res.send(Result.Error("验证码错误"));

   // 检测当前数据库中是否存在用户信息
   const user = await prisma.user.findFirst({
      where: { phone: account, status: { not: "LOGINOUT" } }
   });

   if (!user) return res.send(Result.Error("当前用户不存在"));

   // 当前用户状态 status 0: 注销, 1: 正常, 2: 未激活
   if (user.status == "NOT_ACTIVATED") return res.send(Result.Error("当前用户未激活，请联系管理员激活账户"));

   const token = Token.Encrypt(user.id);
   await redis.set(user.id, JSON.stringify({ token }));
   await prisma.user.update({ where: { id: user.id }, data: { last_login_time: Time.Now() } });

   // start --- 获取用户权限列表

   // 读取路由列表
   const router = await prisma.mp_router.findMany();
   let routerTree;
   // 读取用户当前角色信息
   const role = await prisma.mp_role.findUnique({ where: { id: user.role_id } });
   if (!role) return res.send(Result.Error("当前用户未分配角色"));

   // 如果当前角色为超级管理员，返回所有页面
   if (role.super_admin) {
      routerTree = Utils.ListToTree(router);
   } else {
      const permission = role.permission.split(","); // 将权限字段还原为 id 数组
      const routerMap = new Map<string, PRouter>(); // 创建路由 map 对象，key 为路由 id ，value 为路由信息
      router.forEach(item => routerMap.set(item.id, item)); // 将路由数组转换为 map 对象

      const roleRouter = permission.map(item => routerMap.get(item)); // 遍历权限列表，将符合条件的路由信息组合为新数组

      routerTree = Utils.ListToTree(roleRouter); // 将扁平结构转化为树状结构
   }

   // end --- 获取用户权限列表

   res.send(
      Result.OK({
         token,
         userInfo: {
            name: user.name,
            account: user.account,
            phone: user.phone,
            role_id: user.role_id,
            avatar: user.avatar
         },
         router: routerTree
      })
   );
});

/** 退出登录 */
router.post("/out", async (req, res) => {
   const userId = req.userId;
   console.log("userId", userId);
   /** 删除当前用户在 redis中缓存的数据 */
   try {
      redis.del(userId);
   } catch (error) {}
   res.send(Result.OK());
});

export const login = router;
